home *** CD-ROM | disk | FTP | other *** search
/ Sky at Night 2006 September / SAN CD 9-2006 CD-ROM 16.iso / pc / Software / Network Telescope Control / NTC-Setup.Exe / Source / ntc_server_network.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  2006-03-24  |  48.9 KB  |  2,037 lines

  1. unit ntc_server_network;
  2. {
  3.     Copyright (C) 2004 - 2006 Andrew Sprott
  4.  
  5.     http://astronomy.crysania.co.uk
  6.     astro@trefach.co.uk
  7.  
  8.     This program is free software; you can redistribute it and/or
  9.     modify it under the terms of the GNU General Public License
  10.     as published by the Free Software Foundation; either version 2
  11.     of the License, or (at your option) any later version.
  12.  
  13.     This program is distributed in the hope that it will be useful,
  14.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16.     GNU General Public License for more details.
  17.  
  18.     You should have received a copy of the GNU General Public License
  19.     along with this program; if not, write to the Free Software
  20.     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21. }
  22.  
  23. interface
  24.  
  25. uses
  26.     Windows,
  27.     Messages,
  28.     Variants,
  29.     Classes,
  30.     Graphics,
  31.     Controls,
  32.     Forms,
  33.     Dialogs,
  34.     StdCtrls,
  35.     Buttons,
  36.     CheckLst,
  37.     ExtCtrls,
  38.     SysUtils,
  39.     inifiles,
  40.  
  41.     IdBaseComponent,
  42.     IdComponent,
  43.     IdTCPServer,
  44.     IdResourceStrings,
  45.     IdStack,
  46.     IdGlobal,
  47.     IdSocketHandle,
  48.  
  49.     ntc_server_focus,
  50.     ntc_server_object,
  51.     ntc_server_form;
  52.  
  53. const
  54.     seconds_in=60*60;
  55.     seconds_in_az=360*seconds_in;
  56.     seconds_in_alt=360*seconds_in;
  57.     degrees_in_quarter=90;
  58.     percent_100=65535;
  59.     degrees_in_circle=360;
  60.     minutes_in_degree=60;
  61.     minutes_in_circle=degrees_in_circle*minutes_in_degree;
  62.     minutes_in_semicircle=minutes_in_circle/2;
  63.     hours_in_circle=24;
  64.     minutes_in_hour=60;
  65.     hours_minutes_in_circle=hours_in_circle*minutes_in_hour;
  66.     hours_minutes_in_semicircle=hours_minutes_in_circle/2;
  67.     local_machine=true;
  68.     remote_machine=false;
  69.     read_fail_count=2;
  70.     { network }
  71.     port_number=8383;
  72.     crlf=chr(13)+chr(10);
  73.     { correcting }
  74.     default_intercept=99.834586;
  75.     default_co_efficient_1=0.043221;
  76.     default_co_efficient_2=-0.017952;
  77.     default_co_efficient_3=5.71035432E-05;
  78.  
  79. type
  80.     button_type_set=(
  81.         b_west,
  82.         b_east,
  83.         b_north,
  84.         b_south);
  85.     button_type=set of button_type_set;
  86.  
  87.     p_frame_record=^frame_record;
  88.     frame_record=record
  89.         level:integer;
  90.         outer_frame,
  91.         inner_frame:p_frame_record;
  92.         frame_top,
  93.         frame_left,
  94.         frame_right,
  95.         frame_base:integer;
  96.     end;
  97.  
  98. type
  99.     Tscope_network = class(tform)
  100.         network_panel: TPanel;
  101.         ip_combo: TComboBox;
  102.         refresh_button: TBitBtn;
  103.         edit_port: TEdit;
  104.         scope_server: TIdTCPServer;
  105.         ip_address_label: TLabel;
  106.     enable_network_check: TCheckBox;
  107.     status_log: TMemo;
  108.     clear_log_button: TBitBtn;
  109.     messages_button: TBitBtn;
  110.     io_messages_button: TBitBtn;
  111.     disk_button: TBitBtn;
  112.  
  113.         { form handling }
  114.         procedure formcreate(
  115.             Sender:TObject);
  116.  
  117.         procedure kill;
  118.  
  119.         { scope commands }
  120.         function connected
  121.             :boolean;
  122.  
  123.         Procedure get_info(
  124.             var Name:string;
  125.             var can_query,
  126.                     can_sync,
  127.                     can_goto,
  128.                     can_slew,
  129.                     can_focus,
  130.                     can_track:boolean;
  131.             var focuses:integer);
  132.  
  133.         { network stuff }
  134.         procedure refresh_ip_list;
  135.  
  136.         procedure ip_comboChange(
  137.             Sender: TObject);
  138.  
  139.         procedure start_server;
  140.  
  141.         procedure Stop_Server;
  142.  
  143.         procedure close_network_connection;
  144.  
  145.         procedure update_status_log(
  146.             e:string;
  147.             message_logging:boolean);
  148.  
  149.         procedure update_status_log_check(
  150.             e:string);
  151.  
  152.         procedure change_button(
  153.             button:button_type);
  154.  
  155.         { message handling }
  156.         function process_input(
  157.                     AThread:TIdPeerThread;
  158.                     local:boolean;
  159.             var object_record:tscope_object)
  160.             :string;
  161.  
  162.         function send_message(
  163.             message_string,
  164.             error_string:string)
  165.             :response_type;
  166.  
  167.         function send_message_check(
  168.             message_string:string)
  169.             :response_type;
  170.  
  171.         function get_option_value(
  172.             option:string)
  173.             :string;
  174.  
  175.         function get_float(
  176.                     option:string;
  177.             var exit_result:double)
  178.                     :boolean;
  179.  
  180.         function get_integer(
  181.                     option:string;
  182.             var exit_result:longint)
  183.                     :boolean;
  184.  
  185.         function get_string(
  186.                     option:string;
  187.             var exit_result:string)
  188.                     :boolean;
  189.  
  190.         function get_boolean(
  191.                     option:string;
  192.             var exit_result:boolean)
  193.                     :boolean;
  194.  
  195.         { utilities }
  196.         function update_status_log_failed_check
  197.             :boolean;
  198.  
  199.         procedure update_status_log_failed;
  200.  
  201.         procedure update_status_log_header(
  202.             s:string);
  203.  
  204.         { configuration }
  205.         procedure load_settings;
  206.  
  207.         procedure save_settings;
  208.  
  209.         { events }
  210.         procedure FormShow(
  211.             Sender: TObject);
  212.  
  213.         procedure adjust;
  214.  
  215.         procedure check_activate(
  216.             Sender: TObject);
  217.  
  218.         procedure scope_serverExecute(
  219.             AThread:TIdPeerThread);
  220.  
  221.         procedure edit_portChange(
  222.             Sender: TObject);
  223.  
  224.         procedure refresh_buttonClick(
  225.             Sender: TObject);
  226.  
  227.         procedure form_close_query(
  228.                     Sender: TObject;
  229.             var CanClose: Boolean);
  230.  
  231.         procedure enable_network_checkClick(
  232.             Sender: TObject);
  233.  
  234.         { logging }
  235.         procedure clear_log_buttonClick(
  236.             Sender: TObject);
  237.  
  238.         procedure messages_buttonClick(
  239.             Sender: TObject);
  240.  
  241.         procedure io_messages_buttonClick(
  242.             Sender: TObject);
  243.  
  244.         procedure disk_buttonClick(
  245.             Sender: TObject);
  246.  
  247.     private
  248.         { Private declarations }
  249.         network_enabled,
  250.         network_connected:boolean;
  251.         received_text:widestring;
  252.         ip_count:integer;
  253.         response_text:string;
  254.         option_names,
  255.         option_values:tstrings;
  256.         indented:integer;
  257.         last_line_indented,
  258.         last_line_unindented:boolean;
  259.         fServerRunning:boolean;
  260.         level:integer;
  261.         very_first_frame:frame_record;
  262.         current_frame:p_frame_record;
  263.         current_x,
  264.         current_y:double;
  265.     public
  266.         { Public declarations }
  267.         server_playing:boolean;
  268.         { configuration }
  269.         dimensions:dimensions_record;
  270.         returned_object:tscope_object;
  271.         local_scope_control:boolean;
  272.         message_logging,
  273.         logging:boolean;
  274.         { correcting }
  275.         intercept:extended;
  276.         co_efficient_1,
  277.         co_efficient_2,
  278.         co_efficient_3:extended;
  279.         node_correct:boolean;
  280.         { search }
  281.         frame_level:integer;
  282.  
  283.         { events }
  284.         procedure check_visible_and_show_hide(
  285.             sender:tobject);
  286.  
  287.         procedure hide_form;
  288.         procedure show_form;
  289.  
  290.         { slewing functions }
  291.         procedure reset;
  292.  
  293.         function return_seconds(
  294.             seconds:double)
  295.             :double;
  296.  
  297.         function return_hours(
  298.             degrees,
  299.             y:double)
  300.             :double;
  301.  
  302.     end;
  303.  
  304. var
  305.     scope_network:Tscope_network;
  306.  
  307. implementation
  308.  
  309. {$R *.dfm}
  310.  
  311. Uses
  312.     ntc_server_comms,
  313.     ntc_server_config,
  314.     ntc_server_info,
  315.     ntc_server_observer,
  316.     ntc_server_control,
  317.     ntc_server_search;
  318.  
  319.     { -------------
  320.         form handling
  321.         ------------- }
  322.  
  323. procedure tscope_network.formcreate(
  324.     Sender:TObject);
  325. begin
  326.     { network defaults }
  327.     network_enabled:=false;
  328.     network_connected:=false;
  329.     server_playing:=false;
  330.     ip_address_label.enabled:=false;
  331.     ip_combo.enabled:=false;
  332.     refresh_button.enabled:=false;
  333.     edit_port.enabled:=false;
  334.     local_scope_control:=true;
  335.     returned_object:=nil;
  336.     indented:=0;
  337.     message_logging:=false;
  338.     last_line_indented:=false;
  339.     last_line_unindented:=false;
  340.     intercept:=default_intercept;
  341.     co_efficient_1:=default_co_efficient_1;
  342.     co_efficient_2:=default_co_efficient_2;
  343.     co_efficient_3:=default_co_efficient_3;
  344.     refresh_ip_list;
  345.     current_frame:=nil;
  346.     load_settings;
  347.     reset;
  348. //    scope_control.flip_buttons(true);
  349. end;
  350.  
  351. procedure Tscope_network.kill;
  352. begin
  353.     close_network_connection;
  354. end;
  355.  
  356.     { --------------
  357.         scope commands
  358.         -------------- }
  359.  
  360. function tscope_network.connected
  361.     :boolean;
  362. begin
  363.     if not scope_config.scope_enabled then
  364.         result:=true
  365.     else
  366.         result:=scope_comms.scope_connected;
  367. end;
  368.  
  369. Procedure tscope_network.get_info(
  370.     var Name:string;
  371.     var can_query,
  372.             can_sync,
  373.             can_goto,
  374.             can_slew,
  375.             can_focus,
  376.             can_track:boolean;
  377.     var focuses:integer);
  378. begin
  379.     with scope_config do
  380.          if (scope_type=lx200_type) or
  381.                 (scope_type=autostar_type) then
  382.         begin
  383.             name:=scope_config.model_list.text;
  384.             can_query:=true;
  385.             can_sync:=true;
  386.             can_goto:=true;
  387.             can_slew:=true;
  388.             can_focus:=true;
  389.             can_track:=true;
  390.             focuses:=scope_focus.focus_speeds;
  391.         end
  392.     else
  393.         begin
  394.             name:=scope_config.model_list.text;
  395.             can_query:=true;
  396.             can_sync:=true;
  397.             can_goto:=true;
  398.             can_slew:=true;
  399.             can_focus:=true;
  400.             can_track:=true;
  401.             focuses:=scope_focus.focus_speeds;
  402.         end;
  403. end;
  404.  
  405.     { -------------
  406.         network stuff
  407.         ------------- }
  408.  
  409. procedure tscope_network.refresh_ip_list;
  410. begin
  411.     with ip_combo do
  412.         begin
  413.             Items := GStack.LocalAddresses;
  414.             if items.IndexOf('127.0.0.1')<0 then
  415.                 Items.Insert(0, '127.0.0.1');
  416.             ip_count:=items.count;
  417.         end;
  418. end;
  419.  
  420. procedure tscope_network.ip_comboChange(
  421.     Sender: TObject);
  422. begin
  423.     stop_server;
  424.     start_server;
  425. end;
  426.  
  427. procedure tscope_network.start_server;
  428. var
  429.     Binding:TIdSocketHandle;
  430.     i:integer;
  431.     SL:TStringList;
  432. begin
  433.     SL := TStringList.Create;
  434.     try
  435.         try
  436.             { bindings cannot be cleared until TidTCPServer is inactive }
  437.             scope_server.Bindings.Clear;
  438.             for i := 0 to ip_count-1 do
  439.                 begin
  440.                     Binding:=scope_server.Bindings.Add;
  441.                     Binding.IP:=ip_combo.Items.Strings[i];
  442.                     Binding.Port:=StrToInt(edit_port.Text);
  443.                     SL.append('Server bound to IP '+Binding.IP+
  444.                         ' on port '+edit_port.Text);
  445.                 end;
  446.             scope_server.Active:=true;
  447.             fServerRunning:=scope_server.Active;
  448.             status_log.lines.AddStrings(SL);
  449.             update_status_log('Server started',true);
  450.             if fserverrunning then
  451.                 update_status_log('Server running',true)
  452.             else
  453.                 update_status_log('Server stopped',true);
  454.         except
  455.             on e:exception do
  456.                 begin
  457.                     update_status_log('Server not started : '+e.message,true);
  458.                     fServerRunning:=false;
  459.                 end;
  460.         end;
  461.     finally
  462.         FreeAndNil(SL);
  463.     end;
  464. end;
  465.  
  466. procedure tscope_network.Stop_Server;
  467. begin
  468.     if scope_server.active then
  469.         begin
  470.             scope_server.Active := false;
  471.             scope_server.Bindings.Clear;
  472.             fServerRunning:=not scope_server.Active;
  473.             if fserverrunning then
  474.                 update_status_log('Server stopped',true)
  475.             else
  476.                 update_status_log('Server running',true);
  477.         end;
  478. end;
  479.  
  480. procedure tscope_network.close_network_connection;
  481. begin
  482.     network_enabled:=false;
  483.     scope_server.active:=false;
  484. end;
  485.  
  486. procedure tscope_network.update_status_log(
  487.     e:string;
  488.     message_logging:boolean);
  489. var
  490.     s:string;
  491.     a,m:boolean;
  492. begin
  493.     if message_logging then
  494.         begin
  495.             a:=false;
  496.             m:=false;
  497.             if pos('>>',e)>0 then
  498.                 begin
  499.                     if not last_line_indented then
  500.                         inc(indented,2)
  501.                     else
  502.                         last_line_indented:=false;
  503.                     a:=true;
  504.                 end
  505.             else if pos('<<',e)>0 then
  506.                 begin
  507.                     if not last_line_unindented then
  508.                         dec(indented,2)
  509.                     else
  510.                         last_line_unindented:=false;
  511.                     m:=true;
  512.                 end;
  513.             s:=stringofchar(#32,indented)+e;
  514.             if a then
  515.                 begin
  516.                     inc(indented,2);
  517.                 end
  518.             else if m then
  519.                 begin
  520.                     dec(indented,2);
  521.                 end;
  522.             status_log.Lines.Add(s+#13);
  523.             scope_comms.write_log(s);
  524.         end;
  525. end;
  526.  
  527. procedure tscope_network.update_status_log_check(
  528.     e:string);
  529. begin
  530.     if message_logging then
  531.         update_status_log(e,true);
  532. end;
  533.  
  534. procedure tscope_network.update_status_log_header(
  535.     s:string);
  536. begin
  537.     update_status_log(s+' : ',message_logging);
  538. end;
  539.  
  540. procedure tscope_network.update_status_log_failed;
  541. begin
  542.     update_status_log_check(' !!! failed !!!');
  543.     response_text:='fail';
  544. end;
  545.  
  546. function tscope_network.update_status_log_failed_check
  547.     :boolean;
  548. begin
  549.     if pos(response_text,'fail')=1 then
  550.         begin
  551.             result:=true;
  552.             update_status_log_failed;
  553.         end
  554.     else
  555.         result:=false;
  556. end;
  557.  
  558.     { -----------------
  559.         slewing functions
  560.         ----------------- }
  561.  
  562. procedure tscope_network.change_button(
  563.     button:button_type);
  564. begin
  565.     with scope_search do
  566.          if button>=[b_north] then
  567.         begin
  568.             clock_button.glyph.LoadFromResourceName(hInstance,'NORTH_CLOCK');
  569.             counter_button.glyph.LoadFromResourceName(hInstance,'NORTH_ANTI');
  570.         end
  571.     else if button>=[b_south] then
  572.         begin
  573.             clock_button.glyph.LoadFromResourceName(hInstance,'SOUTH_CLOCK');
  574.             counter_button.glyph.LoadFromResourceName(hInstance,'SOUTH_ANTI');
  575.         end
  576.     else if button>=[b_east] then
  577.         begin
  578.             clock_button.glyph.LoadFromResourceName(hInstance,'EAST_CLOCK');
  579.             counter_button.glyph.LoadFromResourceName(hInstance,'EAST_ANTI');
  580.         end
  581.     else if button>=[b_west] then
  582.         begin
  583.             clock_button.glyph.LoadFromResourceName(hInstance,'WEST_CLOCK');
  584.             counter_button.glyph.LoadFromResourceName(hInstance,'WEST_ANTI');
  585.         end;
  586. end;
  587.  
  588. procedure tscope_network.reset;
  589. var
  590.     t:integer;
  591.     s:double;
  592. begin
  593.     if scope_control.moving_scope then
  594.         begin
  595.             scope_control.moving_scope:=false;
  596.             scope_search.disable_timer;
  597.         end;
  598.     with scope_search do
  599.         begin
  600.             t:=strtointdef(width_edit.text,-1);
  601.             if t=-1 then
  602.                 begin
  603.                     width_edit.text:=inttostr(default_width);
  604.                     camera_width:=default_width;
  605.                 end
  606.             else
  607.                 camera_width:=t;
  608.             t:=strtointdef(height_edit.text,-1);
  609.             if t=-1 then
  610.                 begin
  611.                     height_edit.text:=inttostr(default_height);
  612.                     camera_height:=default_height;
  613.                 end
  614.             else
  615.                 camera_height:=t;
  616.             s:=strtofloatdef(seconds_edit.text,-1);
  617.             if s=-1 then
  618.                 begin
  619.                     seconds_edit.text:=floattostr(default_seconds);
  620.                     seconds_in_pixel:=default_seconds;
  621.                 end
  622.             else
  623.                 seconds_in_pixel:=s;
  624.             t:=strtointdef(timeout_edit.text,-1);
  625.             if t=-1 then
  626.                 begin
  627.                     timeout_edit.text:=inttostr(default_timeout);
  628.                     timeout_interval:=default_timeout;
  629.                 end
  630.             else
  631.                 timeout_interval:=t;
  632.             search_timer.enabled:=false;
  633.             if current_frame<>nil then
  634.                 begin
  635.                     while current_frame^.outer_frame<>nil do
  636.                         current_frame:=current_frame^.outer_frame;
  637.                     while current_frame^.inner_frame<>nil do
  638.                         begin
  639.                             current_frame:=current_frame^.inner_frame;
  640.                             dispose(current_frame^.outer_frame);
  641.                         end;
  642.                 end;
  643.             level:=0;
  644.             window_height:=camera_height;
  645.             window_width:=camera_width;
  646.             timeout_interval:=timeout_interval;
  647.             height_part:=(100-camera_height_part)/100;
  648.             width_part:=(100-camera_width_part)/100;
  649.             with very_first_frame do
  650.                 begin
  651.                     inner_frame:=nil;
  652.                     outer_frame:=nil;
  653.                     level:=0;
  654.                     frame_top:=-(window_height div 2);
  655.                     frame_left:=-(window_width div 2);
  656.                     frame_right:=-frame_left;
  657.                     frame_base:=-frame_top;
  658.                 end;
  659.             current_frame:=@very_first_frame;
  660.             current_x:=0;
  661.             current_y:=0;
  662.         end;
  663. end;
  664.  
  665. function tscope_network.return_seconds(
  666.     seconds:double)
  667.     :double;
  668. begin
  669.     with scope_search do
  670.         result:=seconds*seconds_in_pixel/seconds_in;
  671. end;
  672.  
  673. function tscope_network.return_hours(
  674.     degrees,
  675.     y:double)
  676.     :double;
  677. begin
  678.     degrees:=degrees/(intercept+
  679.         (co_efficient_1*y)+
  680.         (co_efficient_2*(y*y))+
  681.         (co_efficient_3*(y*y*y)))*100;
  682.     result:=degrees/degrees_in_circle*hours_in_circle;
  683. end;
  684.  
  685. function tscope_network.process_input(
  686.             AThread:TIdPeerThread;
  687.             local:boolean;
  688.     var object_record:tscope_object)
  689.             :string;
  690. var
  691.     message_text,
  692.     options_text,
  693.     option_text,
  694.     result_text,
  695.     value_text:widestring;
  696.     i,j:longint;
  697.     s:string;
  698.     options:boolean;
  699.     done:boolean;
  700.     arg_s_1,
  701.     arg_s_2,
  702.     arg_s_3:string;
  703.     arg_i_1:integer;
  704.     arg_b_1,
  705.     arg_b_2,
  706.     arg_b_3,
  707.     arg_b_4,
  708.     arg_b_5,
  709.     arg_b_6:boolean;
  710.     return_object:tscope_object;
  711.     s_ra,s_dec,t_ra,t_dec:double;
  712.  
  713.     function find_option(
  714.                 option:string;
  715.         var variable:string)
  716.                 :boolean;
  717.     begin
  718.         if option_names<>nil then
  719.             begin
  720.                 i:=option_names.indexof(option);
  721.                 if i>=0 then
  722.                     begin
  723.                         variable:=option_values[i];
  724.                         result:=true;
  725.                     end
  726.                 else
  727.                     result:=false;
  728.             end
  729.         else
  730.             result:=false;
  731.     end;
  732.  
  733.     procedure add_option(
  734.         name,
  735.         value:string;
  736.         bracket:boolean);
  737.     begin
  738.         result_text:=result_text+name+'='+value;
  739.         if not bracket then
  740.             result_text:=result_text+',';
  741.     end;
  742.  
  743.     function booleantostr(
  744.         bool:boolean)
  745.         :string;
  746.     begin
  747.         if bool then
  748.             result:='true'
  749.         else
  750.             result:='false';
  751.     end;
  752.  
  753.     function query_high_precision
  754.         :string;
  755.     begin
  756.         if scope_config.high_precision then
  757.             result:='high'
  758.         else
  759.             result:='low';
  760.     end;
  761.  
  762.     function ask(
  763.         s:string)
  764.         :boolean;
  765.     begin
  766.         response_text:=scope_comms.tell(s,return_object);
  767.         result:=pos('ok',copy(response_text,1,2))>0;
  768.     end;
  769.  
  770.     function get_ra_dec
  771.         :boolean;
  772.     begin
  773.         with return_object do
  774.              if ask('get_ra_dec') then
  775.             begin
  776.                 s_ra:=ra/minutes_in_hour;
  777.                 s_dec:=dec/minutes_in_degree;
  778.                 result:=true;
  779.             end
  780.         else
  781.             result:=false;
  782.     end;
  783.  
  784.     procedure move_screen_left;
  785.     begin
  786.         with scope_search do
  787.             begin
  788.                 if local_scope_control then
  789.                     disable_timer;
  790.                 if get_ra_dec then
  791.                     begin
  792.                         s_ra:=s_ra+return_hours(
  793.                             return_seconds(window_width*width_part),s_dec);
  794.                         with scope_network do
  795.                             begin
  796.                                 s:='goto_ra_dec(ra='+floattostr(s_ra)+
  797.                                     ',dec='+floattostr(s_dec)+')';
  798.                                 if not ask(s) then
  799.                                     begin
  800.                                         response_text:='fail';
  801.                                         scope_control.moving_scope:=false;
  802.                                     end
  803.                                 else if local_scope_control then
  804.                                     enable_timer;
  805.                             end;
  806.                     end;
  807.             end;
  808.     end;
  809.  
  810.     procedure move_screen_right;
  811.     begin
  812.         with scope_search do
  813.             begin
  814.                 if local_scope_control then
  815.                     disable_timer;
  816.                 if get_ra_dec then
  817.                     begin
  818.                         s_ra:=s_ra-return_hours(
  819.                             return_seconds(window_width*width_part),s_dec);
  820.                         with scope_network do
  821.                             begin
  822.                                 s:='goto_ra_dec(ra='+floattostr(s_ra)+
  823.                                     ',dec='+floattostr(s_dec)+')';
  824.                                 if not ask(s) then
  825.                                     begin
  826.                                         response_text:='fail';
  827.                                         scope_control.moving_scope:=false;
  828.                                     end
  829.                                 else if local_scope_control then
  830.                                     enable_timer;
  831.                             end;
  832.                     end;
  833.             end;
  834.     end;
  835.  
  836.     procedure move_screen_up;
  837.     begin
  838.         with scope_search do
  839.             begin
  840.                 if local_scope_control then
  841.                     disable_timer;
  842.                 if get_ra_dec then
  843.                     begin
  844.                         s_dec:=s_dec+return_seconds(window_height*height_part);
  845.                         with scope_network do
  846.                             begin
  847.                                 s:='goto_ra_dec(ra='+floattostr(s_ra)+
  848.                                     ',dec='+floattostr(s_dec)+')';
  849.                                 if not ask(s) then
  850.                                     begin
  851.                                         response_text:='fail';
  852.                                         scope_control.moving_scope:=false;
  853.                                     end
  854.                                 else if local_scope_control then
  855.                                     enable_timer;
  856.                             end;
  857.                     end;
  858.             end
  859.     end;
  860.  
  861.     procedure move_screen_down;
  862.     begin
  863.         with scope_search do
  864.             begin
  865.                 if local_scope_control then
  866.                     disable_timer;
  867.                 if get_ra_dec then
  868.                     begin
  869.                         s_dec:=s_dec-return_seconds(window_height*height_part);
  870.                         with scope_network do
  871.                             begin
  872.                                 s:='goto_ra_dec(ra='+floattostr(s_ra)+
  873.                                     ',dec='+floattostr(s_dec)+')';
  874.                                 if not ask(s) then
  875.                                     begin
  876.                                         response_text:='fail';
  877.                                         scope_control.moving_scope:=false;
  878.                                     end
  879.                                 else if local_scope_control then
  880.                                     enable_timer;
  881.                             end;
  882.                     end;
  883.             end
  884.     end;
  885.  
  886.     function send
  887.         :string;
  888.     begin
  889.         result:='nil';
  890.         return_object:=nil;
  891.         response_text:='ok';
  892.         message_text:=received_text;
  893.         trim(message_text);
  894.         if message_text='ok' then
  895.             exit;
  896.         i:=pos('(',message_text);
  897.         if i>0 then
  898.             begin
  899.                 options:=true;
  900.                 options_text:=copy(message_text,i+1,length(message_text));
  901.                 if options_text[length(options_text)]<>')' then
  902.                     begin
  903.                         s:='No closing )'+crlf;
  904.                         if local then
  905.                             result:=s
  906.                         else
  907.                             athread.connection.writeln(s);
  908.                         exit;
  909.                     end;
  910.                 options_text:=copy(options_text,1,length(options_text)-1)+',';
  911.                 option_names:=tstringlist.create;
  912.                 option_values:=tstringlist.create;
  913.                 message_text:=copy(message_text,1,i-1);
  914.                 done:=false;
  915.                 while not done do
  916.                     begin
  917.                         i:=pos(',',options_text);
  918.                         if i>0 then
  919.                             begin
  920.                                 option_text:=copy(options_text,1,i-1);
  921.                                 options_text:=copy(options_text,i+1,length(options_text));
  922.                                 j:=pos('=',option_text);
  923.                                 if j>0 then
  924.                                     begin
  925.                                         value_text:=copy(option_text,j+1,length(option_text));
  926.                                         option_text:=copy(option_text,1,j-1);
  927.                                     end
  928.                                 else
  929.                                     value_text:='';
  930.                                 option_names.add(option_text);
  931.                                 option_values.add(value_text);
  932.                             end
  933.                         else
  934.                             done:=true;
  935.                     end;
  936.             end
  937.         else
  938.             begin
  939.                 options:=false;
  940.                 option_names:=nil;
  941.                 option_values:=nil;
  942.             end;
  943.         arg_s_1:='debug';
  944.         update_status_log_check('process_input >>');
  945.         if message_text='play' then
  946.             begin
  947.                 if not local_scope_control then
  948.                     begin
  949.                         update_status_log_header('play');
  950.                         result_text:='';
  951.                         add_option('model',inttostr(scope_config.model_list.itemindex),true);
  952.                         update_status_log_check('model=('+result_text+')');
  953.                         response_text:='ok=('+result_text+')';
  954.                         server_playing:=true;
  955.                     end
  956.                 else
  957.                     begin
  958.                         update_status_log('Enable network first',true);
  959.                         update_status_log_failed;
  960.                     end;
  961.             end
  962.         else if message_text='bored' then
  963.             begin
  964.                 update_status_log_header('bored');
  965.                 if not server_playing then
  966.                     update_status_log_failed
  967.                 else
  968.                     server_playing:=false;
  969.             end
  970.         else if server_playing or local_scope_control then
  971.              with scope_config do
  972.             begin
  973.                 if message_text='connect' then
  974.                     begin
  975.                         update_status_log_header('connect');
  976.                         if not ask('connect') then
  977.                             update_status_log_failed;
  978.                     end
  979.                 else if message_text='disconnect' then
  980.                     begin
  981.                         update_status_log_header('disconnect');
  982.                         if not ask('disconnect') then
  983.                             update_status_log_failed
  984.                         else if local_scope_control then
  985.                             scope_control.change_panel(false)
  986.                         else
  987.                             scope_control.connect_group.enabled:=true;
  988.                     end
  989.                 else if message_text='connected' then
  990.                     begin
  991.                         update_status_log_header('connected');
  992.                         if connected then
  993.                             response_text:='true'
  994.                         else
  995.                             response_text:='false';
  996.                         response_text:='ok=(connected='+response_text+')';
  997.                         update_status_log_check(response_text);
  998.                     end
  999.                 else if message_text='align' then
  1000.                     begin
  1001.                         update_status_log_header('align');
  1002.                         if find_option('ra',arg_s_1) and
  1003.                              find_option('dec',arg_s_2) then
  1004.                             begin
  1005.                                 s:='align(ra='+arg_s_1+',dec='+arg_s_2+')';
  1006.                                 update_status_log_check(s);
  1007.                                 if not ask(s) then
  1008.                                     response_text:='fail';
  1009.                             end
  1010.                         else
  1011.                             response_text:='fail';
  1012.                         update_status_log_failed_check;
  1013.                     end
  1014.                 else if message_text='get_ra_dec' then
  1015.                     begin
  1016.                         update_status_log_header('get_ra_dec');
  1017.                         if ask('get_ra_dec') then
  1018.                              with return_object do
  1019.                             begin
  1020.                                 result_text:='';
  1021.                                 add_option('ra',floattostr(ra),false);
  1022.                                 add_option('dec',floattostr(dec),true);
  1023.                                 update_status_log_check('('+result_text+')');
  1024.                                 response_text:='ok=('+result_text+')';
  1025.                             end
  1026.                         else
  1027.                             response_text:='fail';
  1028.                         update_status_log_failed_check;
  1029.                     end
  1030.                 else if message_text='get_az_alt' then
  1031.                     begin
  1032.                         update_status_log_header('get_az_alt');
  1033.                         if ask('get_az_alt') then
  1034.                              with return_object do
  1035.                             begin
  1036.                                 result_text:='';
  1037.                                 add_option('alt',floattostr(alt),false);
  1038.                                 add_option('az',floattostr(az),true);
  1039.                                 update_status_log_check('('+result_text+')');
  1040.                                 response_text:='ok=('+result_text+')';
  1041.                             end
  1042.                         else
  1043.                             response_text:='fail';
  1044.                         update_status_log_failed_check;
  1045.                     end
  1046.                 else if message_text='get_info' then
  1047.                     begin
  1048.                         update_status_log_header('get_info');
  1049.                         get_info(arg_s_1,
  1050.                             arg_b_1,arg_b_2,arg_b_3,arg_b_4,arg_b_5,arg_b_6,
  1051.                             arg_i_1);
  1052.                         result_text:='';
  1053.                         add_option('name',arg_s_1,false);
  1054.                         add_option('can_query',booleantostr(arg_b_1),false);
  1055.                         add_option('can_sync',booleantostr(arg_b_2),false);
  1056.                         add_option('can_goto',booleantostr(arg_b_3),false);
  1057.                         add_option('can_slew',booleantostr(arg_b_4),false);
  1058.                         add_option('can_focus',booleantostr(arg_b_5),false);
  1059.                         add_option('can_track',booleantostr(arg_b_6),false);
  1060.                         add_option('focus_speeds',inttostr(arg_i_1),true);
  1061.                         update_status_log_check('('+result_text+')');
  1062.                         response_text:='ok=('+result_text+')';
  1063.                     end
  1064.                 else if message_text='set_observer' then
  1065.                     begin
  1066.                         update_status_log_header('set_observer');
  1067.                         if find_option('lat',arg_s_1) and
  1068.                              find_option('long',arg_s_2) then
  1069.                             begin
  1070.                                 update_status_log_check(
  1071.                                     '('+arg_s_1+' : '+arg_s_2+')');
  1072.                                 with scope_observer do
  1073.                                      set_observer(
  1074.                                     strtofloat(arg_s_1),
  1075.                                     strtofloat(arg_s_2),
  1076.                                     time_zone,
  1077.                                     now);
  1078.                             end
  1079.                         else
  1080.                             update_status_log_failed;
  1081.                     end
  1082.                 else if message_text='query_high_precision' then
  1083.                     begin
  1084.                         update_status_log_header('query_high_precision');
  1085.                         result_text:='';
  1086.                         if scope_enabled then
  1087.                             arg_s_1:=query_high_precision
  1088.                         else
  1089.                             arg_s_1:='low';
  1090.                         add_option('query',arg_s_1,true);
  1091.                         update_status_log_check('('+arg_s_1+')');
  1092.                         response_text:='ok=('+result_text+')';
  1093.                     end
  1094.                 else if message_text='switch_precision' then
  1095.                     begin
  1096.                         result_text:='';
  1097.                         update_status_log_header('switch_precision');
  1098.                         if scope_enabled then
  1099.                             begin
  1100.                                 if ask('switch_precision') then
  1101.                                     begin
  1102.                                         add_option('switch',query_high_precision,true);
  1103.                                         response_text:='ok=('+result_text+')';
  1104.                                         update_status_log_check(response_text);
  1105.                                     end
  1106.                                 else
  1107.                                     update_status_log_failed;
  1108.                             end;
  1109.                     end
  1110.                 else if message_text='stop_focus' then
  1111.                     begin
  1112.                         update_status_log_header('stop_focus');
  1113.                         if not ask('stop_focus') then
  1114.                             response_text:='fail';
  1115.                         update_status_log_failed_check;
  1116.                     end
  1117.                 else if message_text='focus' then
  1118.                     begin
  1119.                         update_status_log_header('focus');
  1120.                         result_text:='';
  1121.                         if find_option('dir',arg_s_1) and
  1122.                              find_option('speed',arg_s_2) and
  1123.                              find_option('timeout',arg_s_3) then
  1124.                             begin
  1125.                                 s:='focus(dir='+arg_s_1[1]+
  1126.                                      ',speed='+arg_s_2+
  1127.                                      ',timeout='+arg_s_3+')';
  1128.                                 if not ask(s)
  1129.                                     then response_text:='fail';
  1130.                             end
  1131.                         else
  1132.                             response_text:='fail';
  1133.                         if not update_status_log_failed_check then
  1134.                             update_status_log_check(s);
  1135.                     end
  1136.                 else if message_text='goto' then
  1137.                     begin
  1138.                         update_status_log_header('goto');
  1139.                         arg_s_1:='debug-1';
  1140.                         arg_s_2:='debug-2';
  1141.                         if find_option('ra',arg_s_1) and
  1142.                              find_option('dec',arg_s_2) then
  1143.                             begin
  1144.                                 s:='goto_ra_dec(ra='+arg_s_1+',dec='+arg_s_2+')';
  1145.                                 if not ask(s) then
  1146.                                     response_text:='fail';
  1147.                             end
  1148.                         else if find_option('az',arg_s_1) and
  1149.                              find_option('alt',arg_s_2) then
  1150.                             begin
  1151.                                 s:='goto_az_alt(az='+arg_s_1+',alt='+arg_s_2+')';
  1152.                                 if not ask(s) then
  1153.                                     response_text:='fail';
  1154.                             end
  1155.                         else
  1156.                             response_text:='fail';
  1157.                         if not update_status_log_failed_check then
  1158.                             update_status_log_check(s);
  1159.                     end
  1160.                 else if message_text='stop' then
  1161.                     begin
  1162.                         update_status_log_header('stop');
  1163.                         if scope_enabled then
  1164.                             begin
  1165.                                 arg_s_1:='stop_all';
  1166.                                 if (response_text<>'fail') and
  1167.                                      not ask(arg_s_1) then
  1168.                                     response_text:='fail';
  1169.                             end;
  1170.                         if not update_status_log_failed_check then
  1171.                             update_status_log_check('('+arg_s_1+')');
  1172.                     end
  1173.                 else if (message_text='increase_tracking') or
  1174.                                 (message_text='decrease_tracking') or
  1175.                                 (message_text='lunar_tracking') or
  1176.                                 (message_text='default_tracking') then
  1177.                     begin
  1178.                         update_status_log_header(message_text);
  1179.                         if not ask(message_text) then
  1180.                             response_text:='fail';
  1181.                         update_status_log_failed_check;
  1182.                     end
  1183.                 else if message_text='stopped' then
  1184.                     begin
  1185.                         result_text:='';
  1186.                         if ask(message_text) then
  1187.                             begin
  1188.                                 add_option('moving',booleantostr(return_object.moving),true);
  1189.                                 response_text:='ok=('+result_text+')';
  1190.                             end
  1191.                         else response_text:='fail';
  1192.                     end
  1193.                 else if message_text='move_screen_down' then
  1194.                     move_screen_down
  1195.                 else if message_text='move_screen_up' then
  1196.                     move_screen_up
  1197.                 else if message_text='move_screen_left' then
  1198.                     move_screen_left
  1199.                 else if message_text='move_screen_right' then
  1200.                     move_screen_right
  1201.                 else if message_text='move_left' then
  1202.                      with scope_control,scope_search do
  1203.                     begin
  1204.                         if local_scope_control then
  1205.                             scope_search.disable_timer;
  1206.                         if get_ra_dec then
  1207.                             begin
  1208.                                 find_option('distance',arg_s_1);
  1209.                                 t_ra:=strtofloatdef(arg_s_1,0);
  1210.                                 if t_ra>0 then
  1211.                                     begin
  1212.                                         if north_label.caption='W' then
  1213.                                             begin
  1214.                                                 s_ra:=s_ra-return_hours(t_ra,s_dec);
  1215.                                                 if s_ra<0 then
  1216.                                                     s_ra:=s_ra+max_degrees;
  1217.                                             end
  1218.                                         else
  1219.                                             begin
  1220.                                                 s_ra:=s_ra+return_hours(t_ra,s_dec);
  1221.                                                 if s_ra>=max_degrees then
  1222.                                                     s_ra:=s_ra-max_degrees;
  1223.                                             end;
  1224.                                         s:='goto_ra_dec(ra='+floattostr(s_ra)+
  1225.                                             ',dec='+floattostr(s_dec)+')';
  1226.                                         if not ask(s) then
  1227.                                             begin
  1228.                                                 response_text:='fail';
  1229.                                                 scope_control.moving_scope:=false;
  1230.                                                 write_status_log('west - failed to move scope');
  1231.                                             end
  1232.                                         else if local_scope_control then
  1233.                                             scope_search.enable_timer;
  1234.                                     end
  1235.                                 else write_status_log('west - wrong parameter');
  1236.                             end
  1237.                         else
  1238.                             write_status_log('west - failed to read position');
  1239.                     end
  1240.                 else if message_text='move_right' then
  1241.                      with scope_control,scope_search do
  1242.                     begin
  1243.                         if local_scope_control then
  1244.                             scope_search.disable_timer;
  1245.                         if get_ra_dec then
  1246.                             begin
  1247.                                 find_option('distance',arg_s_1);
  1248.                                 t_ra:=strtofloatdef(arg_s_1,0);
  1249.                                 if t_ra>0 then
  1250.                                     begin
  1251.                                         if north_label.caption='E' then
  1252.                                             begin
  1253.                                                 s_ra:=s_ra+return_hours(t_ra,s_dec);
  1254.                                                 if s_ra<0 then
  1255.                                                     s_ra:=s_ra+max_degrees;
  1256.                                             end
  1257.                                         else
  1258.                                             begin
  1259.                                                 s_ra:=s_ra-return_hours(t_ra,s_dec);
  1260.                                                 if s_ra>=max_degrees then
  1261.                                                     s_ra:=s_ra-max_degrees;
  1262.                                             end;
  1263.                                         s:='goto_ra_dec(ra='+floattostr(s_ra)+
  1264.                                             ',dec='+floattostr(s_dec)+')';
  1265.                                         if not ask(s) then
  1266.                                             begin
  1267.                                                 response_text:='fail';
  1268.                                                 scope_control.moving_scope:=false;
  1269.                                                 write_status_log('east - failed to move scope');
  1270.                                             end
  1271.                                         else if local_scope_control then
  1272.                                             scope_search.enable_timer;
  1273.                                     end
  1274.                                 else
  1275.                                     write_status_log('east - wrong parameter');
  1276.                             end
  1277.                         else
  1278.                             write_status_log('east - failed to read position');
  1279.                     end
  1280.                 else if message_text='move_up' then
  1281.                      with scope_control do
  1282.                     begin
  1283.                         if local_scope_control then
  1284.                             scope_search.disable_timer;
  1285.                         if get_ra_dec then
  1286.                             begin
  1287.                                 find_option('distance',arg_s_1);
  1288.                                 t_dec:=strtofloatdef(arg_s_1,0);
  1289.                                 if t_dec>0 then
  1290.                                     begin
  1291.                                         if north_label.caption='S' then
  1292.                                             begin
  1293.                                                 s_dec:=s_dec-t_dec;
  1294.                                                 if s_dec<=-max_degrees_dec then
  1295.                                                     s_dec:=-max_degrees_dec-1;
  1296.                                             end
  1297.                                         else
  1298.                                             begin
  1299.                                                 s_dec:=s_dec+t_dec;
  1300.                                                 if s_dec>=max_degrees_dec then
  1301.                                                     s_dec:=max_degrees_dec-1;
  1302.                                             end;
  1303.                                         s:='goto_ra_dec(ra='+floattostr(s_ra)+
  1304.                                             ',dec='+floattostr(s_dec)+')';
  1305.                                         if not ask(s) then
  1306.                                             begin
  1307.                                                 response_text:='fail';
  1308.                                                 scope_control.moving_scope:=false;
  1309.                                                 write_status_log('north - failed to move scope');
  1310.                                             end
  1311.                                         else if local_scope_control then
  1312.                                             scope_search.enable_timer;
  1313.                                     end
  1314.                                 else
  1315.                                     write_status_log('north - wrong parameter');
  1316.                             end
  1317.                         else
  1318.                             write_status_log('north - failed to read position');
  1319.                     end
  1320.                 else if message_text='move_down' then
  1321.                      with scope_control do
  1322.                     begin
  1323.                         if local_scope_control then
  1324.                             scope_search.disable_timer;
  1325.                         if get_ra_dec then
  1326.                             begin
  1327.                                 find_option('distance',arg_s_1);
  1328.                                 t_dec:=strtofloatdef(arg_s_1,0);
  1329.                                 if t_dec>0 then
  1330.                                     begin
  1331.                                         if north_label.caption='N' then
  1332.                                             begin
  1333.                                                 s_dec:=s_dec-t_dec;
  1334.                                                 if s_dec<=-max_degrees_dec then
  1335.                                                     s_dec:=-max_degrees_dec-1;
  1336.                                             end
  1337.                                         else
  1338.                                             begin
  1339.                                                 s_dec:=s_dec+t_dec;
  1340.                                                 if s_dec>=max_degrees_dec then
  1341.                                                     s_dec:=max_degrees_dec-1;
  1342.                                             end;
  1343.                                         s:='goto_ra_dec(ra='+floattostr(s_ra)+
  1344.                                             ',dec='+floattostr(s_dec)+')';
  1345.                                         if not ask(s) then
  1346.                                             begin
  1347.                                                 response_text:='fail';
  1348.                                                 scope_control.moving_scope:=false;
  1349.                                                 write_status_log('south - failed to move scope');
  1350.                                             end
  1351.                                         else if local_scope_control then
  1352.                                             scope_search.enable_timer;
  1353.                                     end
  1354.                                 else
  1355.                                     write_status_log('south - wrong parameter');
  1356.                             end
  1357.                         else
  1358.                             write_status_log('south - failed to read position');
  1359.                     end
  1360.                 else if message_text='break_out' then
  1361.                     begin
  1362.                         with scope_search do
  1363.                             begin
  1364.                                 with current_frame^ do
  1365.                                     begin
  1366.                                         if outer_frame=nil then
  1367.                                             begin
  1368.                                                 new(outer_frame);
  1369.                                                 outer_frame.frame_top:=
  1370.                                                     frame_top-trunc(window_height*height_part);
  1371.                                                 outer_frame.frame_left:=
  1372.                                                     frame_left-trunc(window_width*width_part);
  1373.                                                 outer_frame.frame_right:=
  1374.                                                     frame_right+trunc(window_width*width_part);
  1375.                                                 outer_frame.frame_base:=
  1376.                                                     frame_base+trunc(window_height*height_part);
  1377.                                                 outer_frame.inner_frame:=current_frame;
  1378.                                                 outer_frame.outer_frame:=nil;
  1379.                                                 outer_frame.level:=level+1;
  1380.                                             end;
  1381.                                         current_frame:=outer_frame
  1382.                                     end;
  1383.                                 with current_frame^ do
  1384.                                     begin
  1385.                                         result_text:='';
  1386.                                         if current_x<current_y then
  1387.                                             begin
  1388.                                                 current_x:=frame_left+window_width/2;
  1389.                                                 move_screen_left;
  1390.                                                 change_button([b_west]);
  1391.                                                 result_text:='west';
  1392.                                             end
  1393.                                         else if current_x>current_y then
  1394.                                             begin
  1395.                                                 current_x:=frame_right-window_width/2;
  1396.                                                 move_screen_right;
  1397.                                                 change_button([b_east]);
  1398.                                                 result_text:='east';
  1399.                                             end
  1400.                                         else if current_y<current_x then
  1401.                                             begin
  1402.                                                 current_y:=frame_top+window_height/2;
  1403.                                                 move_screen_up;
  1404.                                                 change_button([b_north]);
  1405.                                                 result_text:='north';
  1406.                                             end
  1407.                                         else
  1408.                                             begin
  1409.                                                 current_y:=frame_base-window_height/2;
  1410.                                                 move_screen_down;
  1411.                                                 change_button([b_south]);
  1412.                                                 result_text:='south';
  1413.                                             end;
  1414.                                     end;
  1415.                                 if result_text<>'' then
  1416.                                     response_text:='ok=(button='+result_text+')';
  1417.                             end;
  1418.                     end
  1419.                 else if message_text='fall_in' then
  1420.                     begin
  1421.                         with scope_search do
  1422.                             begin
  1423.                                 if current_frame^.level>0 then
  1424.                                     begin
  1425.                                         current_frame:=current_frame^.inner_frame;
  1426.                                         with current_frame^ do
  1427.                                             begin
  1428.                                                 if current_x>frame_right then
  1429.                                                     begin
  1430.                                                         current_x:=frame_right-window_width/2;
  1431.                                                         move_screen_left;
  1432.                                                     end
  1433.                                                 else if current_x<frame_left then
  1434.                                                     begin
  1435.                                                         current_x:=frame_left+window_width/2;
  1436.                                                         move_screen_right;
  1437.                                                     end;
  1438.                                                 if current_y>frame_base then
  1439.                                                     begin
  1440.                                                         current_y:=frame_base-window_height/2;
  1441.                                                         move_screen_up;
  1442.                                                     end
  1443.                                                 else if current_y<frame_top then
  1444.                                                     begin
  1445.                                                         current_y:=frame_top+window_height/2;
  1446.                                                         move_screen_down;
  1447.                                                     end;
  1448.                                             end;
  1449.                                     end;
  1450.                             end;
  1451.                     end
  1452.                 else if message_text='clockwise' then
  1453.                     begin
  1454.                         if current_frame^.level>0 then
  1455.                              with current_frame^.inner_frame^,scope_search do
  1456.                             begin
  1457.                                 result_text:='';
  1458.                                 if current_y>frame_base then
  1459.                                     begin
  1460.                                         if current_x<frame_left then
  1461.                                             begin
  1462.                                                 current_y:=current_y-window_height*height_part;
  1463.                                                 change_button([b_west]);
  1464.                                                 result_text:='west';
  1465.                                                 move_screen_up;
  1466.                                             end
  1467.                                         else
  1468.                                             begin
  1469.                                                 if current_x>frame_right then
  1470.                                                     begin
  1471.                                                         change_button([b_south]);
  1472.                                                         result_text:='south';
  1473.                                                     end;
  1474.                                                 current_x:=current_x-window_width*width_part;
  1475.                                                 move_screen_left;
  1476.                                             end;
  1477.                                     end
  1478.                                 else if current_y<frame_top then
  1479.                                     begin
  1480.                                         if current_x>frame_right then
  1481.                                             begin
  1482.                                                 current_y:=current_y+window_height*height_part;
  1483.                                                 change_button([b_east]);
  1484.                                                 result_text:='east';
  1485.                                                 move_screen_down;
  1486.                                             end
  1487.                                         else
  1488.                                             begin
  1489.                                                 if current_x<frame_left then
  1490.                                                     begin
  1491.                                                         change_button([b_north]);
  1492.                                                         result_text:='north';
  1493.                                                     end;
  1494.                                                 current_x:=current_x+window_width*width_part;
  1495.                                                 move_screen_right;
  1496.                                             end;
  1497.                                     end
  1498.                                 else if current_x>frame_right then
  1499.                                     begin
  1500.                                         if current_y>frame_base then
  1501.                                             begin
  1502.                                                 current_x:=current_x-window_width*width_part;
  1503.                                                 change_button([b_south]);
  1504.                                                 result_text:='south';
  1505.                                                 move_screen_left;
  1506.                                             end
  1507.                                         else
  1508.                                             begin
  1509.                                                 current_y:=current_y+window_height*height_part;
  1510.                                                 move_screen_down;
  1511.                                             end;
  1512.                                     end
  1513.                                 else if current_y<frame_top then
  1514.                                     begin
  1515.                                         current_x:=current_x+window_width*width_part;
  1516.                                         change_button([b_north]);
  1517.                                         result_text:='north';
  1518.                                         move_screen_right;
  1519.                                     end
  1520.                                 else
  1521.                                     begin
  1522.                                         current_y:=current_y-window_height*height_part;
  1523.                                         move_screen_up;
  1524.                                     end;
  1525.                                 if result_text<>'' then
  1526.                                     response_text:='ok=(button='+result_text+')';
  1527.                             end;
  1528.                     end
  1529.                 else if message_text='counter' then
  1530.                     begin
  1531.                         if current_frame^.level>0 then
  1532.                              with current_frame^.inner_frame^,scope_search do
  1533.                             begin
  1534.                                 result_text:='';
  1535.                                 if current_y<frame_top then
  1536.                                     begin
  1537.                                         if current_x<frame_left then
  1538.                                             begin
  1539.                                                 current_y:=current_y+window_height*height_part;
  1540.                                                 change_button([b_west]);
  1541.                                                 result_text:='west';
  1542.                                                 move_screen_down;
  1543.                                             end
  1544.                                         else
  1545.                                             begin
  1546.                                                 if current_x>frame_right then
  1547.                                                     begin
  1548.                                                         change_button([b_north]);
  1549.                                                         result_text:='north';
  1550.                                                     end;
  1551.                                                 current_x:=current_x-window_width*width_part;
  1552.                                                 move_screen_left;
  1553.                                             end;
  1554.                                     end
  1555.                                 else if current_y>frame_base then
  1556.                                     begin
  1557.                                         if current_x>frame_right then
  1558.                                             begin
  1559.                                                 current_y:=current_y-window_height*height_part;
  1560.                                                 change_button([b_east]);
  1561.                                                 result_text:='east';
  1562.                                                 move_screen_up;
  1563.                                             end
  1564.                                         else
  1565.                                             begin
  1566.                                                 if current_x<frame_left then
  1567.                                                     begin
  1568.                                                         change_button([b_south]);
  1569.                                                         result_text:='south';
  1570.                                                     end;
  1571.                                                 current_x:=current_x+window_width*width_part;
  1572.                                                 move_screen_right;
  1573.                                             end;
  1574.                                     end
  1575.                                 else if current_x<frame_left then
  1576.                                     begin
  1577.                                         if current_y>frame_base then
  1578.                                             begin
  1579.                                                 current_x:=current_x+window_width*width_part;
  1580.                                                 change_button([b_south]);
  1581.                                                 result_text:='south';
  1582.                                                 move_screen_right;
  1583.                                             end
  1584.                                         else
  1585.                                             begin
  1586.                                                 current_y:=current_y+window_height*height_part;
  1587.                                                 move_screen_down;
  1588.                                             end;
  1589.                                     end
  1590.                                 else if current_y<frame_top then
  1591.                                     begin
  1592.                                         current_x:=current_x-window_width*width_part;
  1593.                                         change_button([b_north]);
  1594.                                         result_text:='north';
  1595.                                         move_screen_left;
  1596.                                     end
  1597.                                 else
  1598.                                     begin
  1599.                                         current_y:=current_y-window_height*height_part;
  1600.                                         move_screen_up;
  1601.                                     end;
  1602.                                 if result_text<>'' then
  1603.                                     response_text:='ok=(button='+result_text+')';
  1604.                             end;
  1605.                     end
  1606.                 else if message_text='reset_search' then
  1607.                     begin
  1608.                         reset;
  1609.                         response_text:='ok';
  1610.                     end
  1611.                 else
  1612.                     response_text:='fail';
  1613.             end
  1614.         else
  1615.             response_text:='fail';
  1616.         result:=response_text;
  1617.         if not local then
  1618.             athread.connection.writeln(response_text+crlf);
  1619.         received_text:='';
  1620.         update_status_log_check('<< process_input');
  1621.         object_record:=return_object;
  1622.         if return_object<>nil then
  1623.             return_object.free;
  1624.     end;
  1625.  
  1626. begin
  1627.     result:=send;
  1628.     if options then
  1629.         begin
  1630.             option_names.free;
  1631.             option_values.free;
  1632.         end;
  1633. end;
  1634.  
  1635.     { -------------------
  1636.         internal networking
  1637.         ------------------- }
  1638.  
  1639. function tscope_network.send_message(
  1640.     message_string,
  1641.     error_string:string)
  1642.     :response_type;
  1643. var
  1644.     e,s,t:string;
  1645.     done,
  1646.     f:boolean;
  1647.     i:integer;
  1648. begin
  1649.     indented:=0;
  1650.     update_status_log_check('send_message >>');
  1651.     result:=[exit_ok];
  1652.     e:='i said : '+message_string;
  1653.     received_text:=message_string;
  1654.     f:=false;
  1655.     s:=process_input(nil,local_machine,returned_object);
  1656.     if s='nil' then
  1657.         begin
  1658.             f:=true;
  1659.             e:=e+' : and received a null repsonse : '+error_string;
  1660.         end
  1661.     else if s<>'' then
  1662.         begin
  1663.             if pos('ok',s)=1 then
  1664.                 begin
  1665.                     if pos('=',s)=3 then
  1666.                         begin
  1667.                             if pos('(',s)=4 then
  1668.                                 begin
  1669.                                     if option_names=nil then
  1670.                                         begin
  1671.                                             option_names:=tstringlist.create;
  1672.                                             option_values:=tstringlist.create;
  1673.                                         end;
  1674.                                     s:=copy(s,5,length(s));
  1675.                                     s[length(s)]:=',';
  1676.                                     option_names.clear;
  1677.                                     option_values.Clear;
  1678.                                     done:=false;
  1679.                                     while not done do
  1680.                                         begin
  1681.                                             i:=pos(',',s);
  1682.                                             if i>0 then
  1683.                                                 begin
  1684.                                                     t:=copy(s,1,i-1);
  1685.                                                     s:=copy(s,i+1,length(s));
  1686.                                                     i:=pos('=',t);
  1687.                                                     option_names.Add(copy(t,1,i-1));
  1688.                                                     option_values.add(copy(t,i+1,length(t)));
  1689.                                                 end
  1690.                                             else
  1691.                                                 done:=true;
  1692.                                         end;
  1693.                                 end
  1694.                         end;
  1695.                 end
  1696.             else if pos('fail',s)=1 then
  1697.                 begin
  1698.                     f:=true;
  1699.                     e:=e+' : but reported : '+error_string;
  1700.                 end
  1701.         end;
  1702.     if f then
  1703.         begin
  1704.             with scope_control do
  1705.                 begin
  1706.                     ignore_event_north:=event_0;
  1707.                     ignore_event_south:=event_0;
  1708.                     ignore_event_west:=event_0;
  1709.                     ignore_event_east:=event_0;
  1710.                 end;
  1711.             result:=[exit_fail];
  1712.         end;
  1713.     update_status_log_check(e);
  1714.     update_status_log_check('<< send_message');
  1715. end;
  1716.  
  1717. function tscope_network.send_message_check(
  1718.     message_string:string)
  1719.     :response_type;
  1720. begin
  1721.     result:=send_message(message_string,no_response);
  1722. end;
  1723.  
  1724. function tscope_network.get_option_value(
  1725.     option:string)
  1726.     :string;
  1727. var
  1728.     i:integer;
  1729. begin
  1730.     i:=option_names.indexof(option);
  1731.     if i>=0 then
  1732.         result:=option_values[i]
  1733.     else
  1734.         result:='';
  1735. end;
  1736.  
  1737. function tscope_network.get_float(
  1738.             option:string;
  1739.     var exit_result:double)
  1740.             :boolean;
  1741. var
  1742.     s:string;
  1743. begin
  1744.     s:=get_option_value(option);
  1745.     if s<>'' then
  1746.         begin
  1747.             exit_result:=strtofloat(s);
  1748.             result:=true;
  1749.         end
  1750.     else
  1751.         result:=false;
  1752. end;
  1753.  
  1754. function tscope_network.get_integer(
  1755.             option:string;
  1756.     var exit_result:longint)
  1757.             :boolean;
  1758. var
  1759.     s:string;
  1760. begin
  1761.     s:=get_option_value(option);
  1762.     if s<>'' then
  1763.         begin
  1764.             exit_result:=strtoint(s);
  1765.             result:=true;
  1766.         end
  1767.     else
  1768.         result:=false;
  1769. end;
  1770.  
  1771. function tscope_network.get_string(
  1772.             option:string;
  1773.     var exit_result:string)
  1774.             :boolean;
  1775. var
  1776.     s:string;
  1777. begin
  1778.     s:=get_option_value(option);
  1779.     if s<>'' then
  1780.         begin
  1781.             exit_result:=s;
  1782.             result:=true;
  1783.         end
  1784.     else
  1785.         result:=false;
  1786. end;
  1787.  
  1788. function tscope_network.get_boolean(
  1789.             option:string;
  1790.     var exit_result:boolean)
  1791.             :boolean;
  1792. var
  1793.     s:string;
  1794. begin
  1795.     s:=get_option_value(option);
  1796.     if s<>'' then
  1797.         begin
  1798.             exit_result:=s='true';
  1799.             result:=true;
  1800.         end
  1801.     else
  1802.         result:=false;
  1803. end;
  1804.  
  1805.     { -----------------------
  1806.         configuration functions
  1807.         ----------------------- }
  1808.  
  1809. procedure tscope_network.load_settings;
  1810. begin
  1811.     ini_file:=tinifile.create(application_path+'server.ini');
  1812.     with ini_file do
  1813.         begin
  1814.             message_logging:=ReadBool('network','message_logging',false);
  1815.             { form }
  1816.             scope.get_dimensions(scope_network,@dimensions,'network',ini_file);
  1817.             left:=dimensions.form_left;
  1818.             top:=dimensions.form_top;
  1819.             visible:=readbool('network','visible',false);
  1820.         end;
  1821.     ini_file.Free;
  1822. end;
  1823.  
  1824. procedure tscope_network.save_settings;
  1825. begin
  1826.     with ini_file do
  1827.         begin
  1828.             writeBool('network','message_logging',message_logging);
  1829.             { form }
  1830.             scope.find_vdu(scope_network,@dimensions);
  1831.             scope.write_dimensions(@dimensions,left,top,'network',ini_file);
  1832.             writebool('network','visible',visible);
  1833.         end;
  1834. end;
  1835.  
  1836.     { ------
  1837.         events
  1838.         ------ }
  1839.  
  1840. procedure Tscope_network.FormShow(
  1841.     Sender: TObject);
  1842. begin
  1843.     with dimensions do
  1844.         begin
  1845.             top:=form_top;
  1846.             left:=form_left;
  1847.         end;
  1848.     if scope_comms.file_logging then
  1849.         disk_button.Font.style:=[fsbold]
  1850.     else
  1851.         disk_button.font.style:=[];
  1852.     if scope_comms.io_logging then
  1853.         io_messages_button.Font.style:=[fsbold]
  1854.     else
  1855.         io_messages_button.font.style:=[];
  1856.     if message_logging then
  1857.         messages_button.Font.style:=[fsbold]
  1858.     else
  1859.         messages_button.font.style:=[];
  1860. end;
  1861.  
  1862. procedure tscope_network.adjust;
  1863. begin
  1864.     with dimensions do
  1865.         begin
  1866.             form_top:=trunc(form_top/last_screen_height*current_height);
  1867.             form_left:=trunc(form_left/last_screen_width*current_width);
  1868.         end;
  1869.     if visible then
  1870.         show;
  1871. end;
  1872.  
  1873. procedure tscope_network.check_visible_and_show_hide(
  1874.     sender:tobject);
  1875. begin
  1876.     if visible then
  1877.         hide_form
  1878.     else
  1879.         show_form;
  1880.     scope.show_hide(sender,visible);
  1881. end;
  1882.  
  1883. procedure tscope_network.hide_form;
  1884. begin
  1885.     with dimensions do
  1886.         begin
  1887.             form_top:=top;
  1888.             form_left:=left;
  1889.         end;
  1890.     Visible:=false;
  1891. end;
  1892.  
  1893. procedure tscope_network.show_form;
  1894. begin
  1895.     Visible:=true;
  1896. end;
  1897.  
  1898. procedure Tscope_network.check_activate(
  1899.     Sender: TObject);
  1900. begin
  1901.     scope.form_activate(scope_network,@dimensions);
  1902. end;
  1903.  
  1904. procedure Tscope_network.form_close_query(
  1905.             Sender: TObject;
  1906.     var CanClose: Boolean);
  1907. begin
  1908.     canclose:=false;
  1909.     visible:=false;
  1910.     with dimensions do
  1911.         begin
  1912.             form_top:=top;
  1913.             form_left:=left;
  1914.         end;
  1915. end;
  1916.  
  1917. procedure tscope_network.scope_serverExecute(
  1918.     AThread:TIdPeerThread);
  1919. var
  1920.     returned_object:tscope_object;
  1921. begin
  1922.     received_text:=athread.connection.readln(
  1923.         crlf,read_fail_count,max_buffer_size);
  1924.     if received_text<>'' then
  1925.         begin
  1926.             indented:=0;
  1927.             update_status_log_check(
  1928.                 'start remote command : '+FormatDateTime('hh:mm:ss.zzz',now));
  1929.             process_input(athread,remote_machine,returned_object);
  1930.             update_status_log_check(
  1931.                 'end remote command : '+FormatDateTime('hh:mm:ss.zzz',now));
  1932.         end;
  1933. end;
  1934.  
  1935. procedure tscope_network.edit_portChange(
  1936.     Sender: TObject);
  1937. begin
  1938.     stop_server;
  1939.     start_server;
  1940. end;
  1941.  
  1942. procedure tscope_network.refresh_buttonClick(
  1943.     Sender: TObject);
  1944. begin
  1945.     refresh_ip_list;
  1946. end;
  1947.  
  1948. procedure Tscope_network.enable_network_checkClick(
  1949.     Sender: TObject);
  1950. begin
  1951.     with enable_network_check do
  1952.         begin
  1953.             scope_control.connect_group.enabled:=not checked;
  1954.             if not checked then
  1955.                 begin
  1956.                     server_playing:=false;
  1957.                     stop_server;
  1958.                 end
  1959.             else scope_control.disconnect_from_scope;
  1960.             local_scope_control:=not checked;
  1961.             ip_address_label.enabled:=checked;
  1962.             ip_combo.enabled:=checked;
  1963.             refresh_button.enabled:=checked;
  1964.             edit_port.enabled:=checked;
  1965.         end;
  1966. end;
  1967.  
  1968.     { --------------
  1969.         logging events
  1970.         -------------- }
  1971.  
  1972. procedure tscope_network.clear_log_buttonClick(
  1973.     Sender: TObject);
  1974. begin
  1975.     status_log.Lines.Clear;
  1976.     update_status_log_check('log cleared');
  1977. end;
  1978.  
  1979. procedure tscope_network.messages_buttonClick(
  1980.     Sender: TObject);
  1981. begin
  1982.     if not message_logging then
  1983.         begin
  1984.             message_logging:=true;
  1985.             messages_button.font.style:=[fsbold];
  1986.             update_status_log_check('messages enabled');
  1987.         end
  1988.     else
  1989.         begin
  1990.             messages_button.font.style:=[];
  1991.             update_status_log_check('messages disabled');
  1992.             message_logging:=false;
  1993.         end;
  1994. end;
  1995.  
  1996. procedure tscope_network.io_messages_buttonClick(
  1997.     Sender: TObject);
  1998. begin
  1999.     with scope_comms do
  2000.          if not io_logging then
  2001.         begin
  2002.             io_logging:=true;
  2003.             io_messages_button.font.style:=[fsbold];
  2004.             update_status_log_check('IO messages enabled');
  2005.         end
  2006.     else
  2007.         begin
  2008.             io_messages_button.font.style:=[];
  2009.             update_status_log_check('IO messages disabled');
  2010.             io_logging:=false;
  2011.         end;
  2012. end;
  2013.  
  2014. procedure tscope_network.disk_buttonClick(
  2015.     Sender: TObject);
  2016. begin
  2017.     with scope_network do
  2018.         begin
  2019.             if logging then
  2020.                 begin
  2021.                     logging:=false;
  2022.                     disk_button.font.style:=[];
  2023.                     update_status_log_check('logging disabled');
  2024.                 end
  2025.             else
  2026.                 begin
  2027.                     logging:=true;
  2028.                     scope_comms.init_log_file('ntc-client.log');
  2029.                     disk_button.font.style:=[fsbold];
  2030.                     update_status_log_check('logging enabled');
  2031.                 end;
  2032.         end;
  2033. end;
  2034.  
  2035. end.
  2036.  
  2037.